"use client";
import { HubConnectionBuilder, HubConnectionState } from "@microsoft/signalr"; // 导入 SignalR 库
import { OrbitControls, useGLTF } from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import { Modal } from "antd";
import { Key, useEffect, useState } from "react";
import * as THREE from "three";

//定义 堆垛机信息参数
interface SrmInfo {
  srmCode: number; //堆垛机编码
  errCode: string; //错误代码
  runMode: string; //运行模式
  x: number; //X坐标
  y: number; //Y坐标
  z: number; //Z坐标
  serialNo: number; //流水号
  funcCode: number; //功能码
  palletCode: number; //托盘编码
  row: number; //排
  col: number; //列
  layer: number; //层
  shelfNo: number; //库台号
  hasGoods: boolean; //是否有货物
}
//定义 输送线信息参数
interface CovInfo {
  deviceCode: string; //设备编码
  errCode: string; //错误代码
  runMode: string; //出入模式
  hasGoods: boolean; //上料口侧是否有货物   1巷道
  hasGoodsCache: boolean; //缓存侧是否有货物  2巷道
  hasGoodsIn: boolean; //入库口侧是否有货物
  hasGoodsMove: boolean; //移载平台侧是否有货物  移载平台
  x: number; //X坐标
  z: number; //Z坐标
  status: string; //设备状态
  onCode: string; //上料口码
  midCode: string; //缓存口码
  downCode: string; //下料口码
}
//定义 货物信息参数
interface GoodsInfo {
  x: number; //X坐标
  y: number; //Y坐标
  z: number; //Z坐标
  palletCode: string; //托盘编码
  binName: string; //库位名称
  binNo: string; //库位号
  materialName: string; //材质名称
  materialNo: string; //材质号
  inTime: string; //入库时间
  loadType: string; //装载类型
}

// 定义 主场景 组件
function MainScene({
  url,
  position,
  onClick,
}: {
  url: string;
  position: THREE.Vector3;
  onClick: () => void;
}) {
  const { scene } = useGLTF(url); // 加载 GLB 模型
  scene.scale.set(1, 1, 1); // 反转 Y 轴
  return (
    <primitive
      object={scene}
      onClick={onClick} // 添加点击事件处理
      position={position} // 设置位置
    />
  ); // 使用 primitive 渲染导入的模型
}

// 定义 子场景 组件
function SubScene({
  url,
  position,
  onClick,
  color,
  info,
}: {
  url: string;
  position: THREE.Vector3;
  onClick: (
    position: THREE.Vector3,
    color: THREE.Color,
    info: GoodsInfo
  ) => void;
  color: THREE.Color;
  info: GoodsInfo;
}) {
  // 使用 useGLTF 加载模型
  const { scene } = useGLTF(url);
  const model = scene.clone(); // 克隆模型
  model.scale.set(1, 1, 1); // 反转 Y 轴

  // 动态设置模型的颜色
  useEffect(() => {
    model.traverse((child) => {
      if (child instanceof THREE.Mesh) {
        // 为每个模型创建独立的材质
        child.material = new THREE.MeshStandardMaterial({ color: color });
      }
    });
  }, [color, model]);

  return (
    // 使用 primitive 渲染导入的模型
    <primitive
      object={model}
      onClick={() => onClick(position, color, info)}
      position={position}
    />
  );
}

// 定义 其他 组件
function Other({
  url,
  position,
  onClick,
  infom,
}: {
  url: string;
  position: THREE.Vector3;
  onClick: (position: any, infom: SrmInfo | CovInfo[]) => void;
  infom: any;
}) {
  // 使用 useGLTF 加载模型
  const { scene } = useGLTF(url);
  const model = scene.clone(); // 克隆模型
  model.scale.set(1, 1, 1); // 反转 Y 轴

  return (
    // 使用 primitive 渲染导入的模型
    <primitive
      object={model}
      onClick={() => onClick(position, infom)}
      position={position}
    />
  );
}

// 定义 非点击物品 组件
function Forks({ url, position }: { url: string; position: THREE.Vector3 }) {
  // 使用 useGLTF 加载模型
  const { scene } = useGLTF(url);
  const model = scene.clone(); // 克隆模型
  model.scale.set(1, 1, 1); // 反转 Y 轴

  return (
    // 使用 primitive 渲染导入的模型
    <primitive object={model} position={position} />
  );
}

export default function Screen() {
  const [positions, setPositions] = useState([new THREE.Vector3(0, 0.735, 0)]); // 用于存储当前物品的位置
  const [wpositions, setwPositions] = useState([
    new THREE.Vector3(0, 0.735, 0),
  ]); // 用于存储设备当前货物的位置
  //定义 Port 设备
  const [portpositions] = useState([
    new THREE.Vector3(44.0255, 0.6, 5.3975), //12号port
    new THREE.Vector3(44.0255, 0.6, 1.5975), //34号port
    new THREE.Vector3(-2.1505, 0.6, 1.5975), //56号port
  ]); // 用于存储 Port 设备的位置
  //定义 CV 设备
  const [cvpositions] = useState([
    new THREE.Vector3(32.1853, 0.504, 5.42846), //1号cv
    new THREE.Vector3(31.45, 0.504, 5.42846), //2号cv
    new THREE.Vector3(10.4174, 0.504, 5.42846), //3号cv
    new THREE.Vector3(9.6821, 0.504, 5.42846), //4号cv
    new THREE.Vector3(32.1853, 0.504, 3.52846), //5号cv
    new THREE.Vector3(31.45, 0.504, 3.52846), //6号cv
    new THREE.Vector3(10.4174, 0.504, 3.52846), //7号cv
    new THREE.Vector3(9.6821, 0.504, 3.52846), //8号cv
    new THREE.Vector3(32.1853, 0.504, 1.62846), //9号cv
    new THREE.Vector3(31.45, 0.504, 1.62846), //10号cv
    new THREE.Vector3(10.4174, 0.504, 1.62846), //11号cv
    new THREE.Vector3(9.6821, 0.504, 1.62846), //12号cv
  ]); // 用于存储 CV 设备的位置
  // 定义 堆垛机主体 只改第一位数字在轨道上的位置
  const [srmpositions] = useState([
    new THREE.Vector3(2, 0, 6.3475), //1号堆垛机
    new THREE.Vector3(2, 0, 4.4475), //2号堆垛机
    new THREE.Vector3(2, 0, 2.5475), //3号堆垛机
    new THREE.Vector3(2, 0, 0.647498), //4号堆垛机
  ]); // 用于存储堆垛机的位置
  // 定义 堆垛机支座 只改第二位数字在堆垛机主体上的位置
  const [nforkpositions] = useState([
    new THREE.Vector3(2, 2, 6.3475), //1
    new THREE.Vector3(2, 3, 4.4475), //2
    new THREE.Vector3(2, 2, 2.5475), //3
    new THREE.Vector3(2, 1, 0.647498), //4
  ]);
  // 定义 堆垛机支座 是否有货，使用无货的位置。
  const [fork1positions, setFork1positions] = useState([
    new THREE.Vector3(2, 2, 6.3475),
  ]);
  const [fork2positions, setFork2positions] = useState([
    new THREE.Vector3(2, 3, 4.4475),
  ]);
  const [fork3positions, setFork3positions] = useState([
    new THREE.Vector3(2, 2, 2.5475),
  ]);
  const [fork4positions, setFork4positions] = useState([
    new THREE.Vector3(2, 1, 0.647498),
  ]);
  // 定义 堆垛机信息数组
  const [srminfo, setSrminfo] = useState<SrmInfo[]>([]); // 用于存储堆垛机信息
  // 定义 输送线信息数组
  const [covinfo, setCovinfo] = useState<CovInfo[]>([]); // 用于存储输送线信息0-11为cv 12-17为port
  // 用来存储当前堆垛机或设备的错误代码的状态
  const [errorCodes, setErrorCodes] = useState<Record<string, string>>({
    srm1: "无",
    srm2: "无",
    srm3: "无",
    srm4: "无",
    cv1: "无",
    cv2: "无",
    cv3: "无",
    cv4: "无",
    cv5: "无",
    cv6: "无",
    cv7: "无",
    cv8: "无",
    cv9: "无",
    cv10: "无",
    cv11: "无",
    cv12: "无",
    port1: "无",
    port2: "无",
    port3: "无",
    port4: "无",
    port5: "无",
    port6: "无",
  });
  // 更新错误代码的方法
  const updateErrorCode = (deviceCode: string, newErrorCode: string) => {
    setErrorCodes((prev) => ({
      ...prev,
      [deviceCode]: newErrorCode,
    }));
  };

  // 初始化 SignalR 连接
  const getConnection = new HubConnectionBuilder()
    .withUrl("http://192.168.3.101:3254/api/qdsignalhub") // 替换为你的 GET 接口 SignalR Hub URL
    .build();

  useEffect(() => {
    // 启动连接并设置数据接收处理
    const startConnections = async () => {
      try {
        // 检查连接状态并在必要时停止连接
        if (getConnection.state !== HubConnectionState.Disconnected) {
          await getConnection.stop(); // 停止现有连接
        }

        // 启动 SignalR 连接
        await getConnection.start();
        // console.log("GET SignalR connected.");

        // 注册接收 Srm 数据的处理
        getConnection.on("ReceiveSrmData", (data) => {
          const info: SrmInfo = JSON.parse(data);
          // console.log("Received Srm Data: ", info);
          // 根据数据更新堆垛机位置
          updatePositions(data);
          // 根据数据更新错误代码
          updateErrorCode(
            `srm${info.srmCode}`,
            info.errCode == null ? "无" : info.errCode
          );
        });

        // 注册接收 Cov 数据的处理
        getConnection.on("ReceiveCovData", (data) => {
          const info: CovInfo = JSON.parse(data);
          // 根据数据更新货物位置
          updateMacPositions(data);
          // 根据数据更新错误代码
          updateErrorCode(
            info.deviceCode,
            info.errCode == null ? "无" : info.errCode
          );
        });

        // 注册接收 货架货物 数据的处理
        getConnection.on("ReceiveBasWBinQDData", (data) => {
          // 根据数据更新货物位置
          updatewPositions(data);
        });
      } catch (err) {
        console.error("Error while starting connections: ", err);
      }
    };

    startConnections();

    // 清理连接
    return () => {
      getConnection.stop(); // 停止 GET SignalR 连接
    };
  }, []);

  //更新货物在设备上的位置
  function updateMacPositions(responseData: string) {
    const item: CovInfo = JSON.parse(responseData);
    item.errCode = item.errCode == null ? "无" : item.errCode;
    const deviceCode = item.deviceCode; // 获取设备编码

    // 根据 deviceCode 更新 covinfo 数组
    if (deviceCode.startsWith("CV")) {
      // 提取 CV 编号
      const index = parseInt(deviceCode.replace("CV", ""), 10); // 获取 CV 编号
      if (index >= 1 && index <= 12) {
        // 确保索引在 1-12 之间
        covinfo[index - 1] = item; // 更新 covinfo 数组 0-11 为 CV1-CV12
      }
    } else if (deviceCode.startsWith("PORT")) {
      // 提取 PORT 编号
      const index = parseInt(deviceCode.replace("PORT", ""), 10); // 获取 PORT 编号
      if (index >= 1 && index <= 6) {
        // 确保索引在 1-6 之间
        covinfo[12 + index - 1] = item; // 更新 covinfo 数组 12-17 为 PORT1-PORT6
      }
    }
    setCovinfo(covinfo); // 更新 covinfo 数组
    //处理货物显示
    goodsDisplay(covinfo);
  }
  //cv port货物显示
  const goodsDisplay = (covinfo: CovInfo[]) => {
    //对covinfo数组进行处理
    const cvinfo = covinfo.slice(0, 12); //cv信息
    const portinfo = covinfo.slice(12); //port信息
    //cvinfo数组处理
    const goods: THREE.Vector3[] = [];

    for (let i = 0; i < cvinfo.length; i++) {
      if (cvinfo[i] == null) {
        continue;
      }
      let x: number;
      let z: number;
      //i为0，4，8时x为32.1987，i为1，5，9时x为31.4503，i为2，6，10时x为10.4174，i为3，7，11时x为9.6821
      if (i % 4 == 0) {
        x = 32.1987;
      } else if (i % 4 == 1) {
        x = 31.4503;
      } else if (i % 4 == 2) {
        x = 10.4174;
      } else {
        x = 9.6821;
      }
      if (cvinfo[i].hasGoods == true) {
        //i为0-3时z为5.7 i为4-7时z为3.8 i为8-11时z为1.9
        if (i < 4) {
          z = 5.7;
        } else if (i < 8) {
          z = 3.8;
        } else {
          z = 1.9;
        }
        goods.push(new THREE.Vector3(z, 1, z));
      }
      if (cvinfo[i].hasGoodsCache == true) {
        //i为0-3时z为5.135 i为4-7时z为3.235 i为8-11时z为1.335
        if (i < 4) {
          z = 5.135;
        } else if (i < 8) {
          z = 3.235;
        } else {
          z = 1.335;
        }
        goods.push(new THREE.Vector3(x, 1, z));
      }
    }
    //portinfo数组处理
    for (let i = 0; i < portinfo.length; i++) {
      if (portinfo[i] == null) {
        continue;
      }
      let x: number;
      let z: number;
      //i为0时z为5.7，i为1时z为5.135，i为2和4时z为1.9，i为3和5时z为1.335
      if (i == 0) {
        z = 5.7;
      } else if (i == 1) {
        z = 5.135;
      } else if (i == 2 || i == 4) {
        z = 1.9;
      } else {
        z = 1.335;
      }
      if (portinfo[i].hasGoods == true) {
        //i为0-3时x为45.1075 i为4-5时x为-3.2325
        if (i < 4) {
          x = 45.1075;
        } else {
          x = -3.2325;
        }
        goods.push(new THREE.Vector3(x, 1.2, z));
      }
      if (portinfo[i].hasGoodsCache == true) {
        //i为0-3时x为44.0344 i为4-5时x为-2.155
        if (i < 4) {
          x = 44.0344;
        } else {
          x = -2.155;
        }
        goods.push(new THREE.Vector3(x, 1.2, z));
      }
      if (portinfo[i].hasGoodsIn == true) {
        //i为0-3时x为42.9525 i为4-5时x为-1.0775
        if (i < 4) {
          x = 42.9525;
        } else {
          x = -1.0775;
        }
        goods.push(new THREE.Vector3(x, 1.2, z));
      }
    }

    setwPositions(goods); // 更新设备货物位置
  };

  // 更新货物位置和颜色
  function updatewPositions(responseData: GoodsInfo[]) {
    const data: GoodsInfo[] = responseData; // 解析并断言类型
    const vectors = data.map(
      (item) => new THREE.Vector3(item.x, item.y, item.z)
    );
    replacePositions(vectors, "#2bae85");
    updatePositionsInfo(vectors, data);
  }

  //更新货物位置和颜色
  const replacePositions = (newPositions: THREE.Vector3[], color: string) => {
    setPositions(newPositions);

    // 使用 map 方法将每个 THREE.Vector3 对象转换为字符串
    const newColorMap = newPositions.reduce((acc, vector) => {
      acc[`${vector.x},${vector.y},${vector.z}`] = new THREE.Color(color);
      return acc;
    }, {} as Record<string, THREE.Color>);

    setColorMap(newColorMap); // 更新颜色映射
  };

  // 坐标到颜色的映射表
  const [colorMap, setColorMap] = useState<Record<string, THREE.Color>>({
    "0,0.735,0": new THREE.Color("#2bae85"),
  });

  //更新货物位置信息
  const updatePositionsInfo = (
    newPositions: THREE.Vector3[],
    goodsinfo: GoodsInfo[]
  ) => {
    const newPositionInfoMap = newPositions.reduce((acc, vector) => {
      // 查找与当前vector坐标匹配的goodsinfo对象
      const matchedGoodsInfo = goodsinfo.find(
        (info) =>
          info.x === vector.x && info.y === vector.y && info.z === vector.z
      );

      // 如果找到了匹配的goodsinfo，就将它赋值；否则可以适当处理（如设为null或其他默认值）
      if (matchedGoodsInfo) {
        acc[`${vector.x},${vector.y},${vector.z}`] = matchedGoodsInfo;
      } else {
        // 这里可以选择不赋值，或者可以赋值为一个默认的GoodsInfo对象
        acc[`${vector.x},${vector.y},${vector.z}`] = {
          x: vector.x,
          y: vector.y,
          z: vector.z,
          palletCode: "",
          binName: "",
          binNo: "",
          materialName: "",
          materialNo: "",
          inTime: "",
          loadType: "",
        }; // 创建一个默认的GoodsInfo
      }

      return acc;
    }, {} as Record<string, GoodsInfo>);

    setPositionInfoMap(newPositionInfoMap); // 更新位置信息映射
  };
  //坐标到信息的映射表
  const [positionInfoMap, setPositionInfoMap] = useState<
    Record<string, GoodsInfo>
  >({
    "0,0.735,0": {
      x: 0,
      y: 0,
      z: 0,
      palletCode: "",
      binName: "",
      binNo: "",
      materialName: "",
      materialNo: "",
      inTime: "",
      loadType: "",
    },
  });

  // 更新堆垛机位置和有货无货的函数
  function updatePositions(responseData: string) {
    // 解析 JSON 字符串
    const data: SrmInfo = JSON.parse(responseData); // 解析并断言类型
    data.x = data.x / 1000000; // 坐标单位转换为米
    data.z = data.z / 100000; // 坐标单位转换为米
    //非标项目堆垛机轨道修正
    if (data.srmCode === 1) {
      data.x = 42.59 - data.x; // 修正坐标
    }
    if (data.srmCode === 2) {
      data.x = 42.59 - data.x; // 修正坐标
    }
    if (data.srmCode === 3) {
      data.x = 42.59 - data.x; // 修正坐标
    }
    if (data.srmCode === 4) {
      data.x = 42.59 - data.x; // 修正坐标
    }
    //更新堆垛机地址
    srmpositions[data.srmCode - 1].x = data.x;
    //更新堆垛机支座位置
    nforkpositions[data.srmCode - 1].x = data.x;
    nforkpositions[data.srmCode - 1].y = data.z; //z是堆垛机升降轴，y在这里是支座的高度
    //更新堆垛机支座是否有货
    switch (data.srmCode) {
      case 1:
        if (data.hasGoods == true) {
          setFork1positions([nforkpositions[0]]);
        } else {
          setFork1positions([]);
        }
        break;
      case 2:
        if (data.hasGoods == true) {
          setFork2positions([nforkpositions[1]]);
        } else {
          setFork2positions([]);
        }
        break;
      case 3:
        if (data.hasGoods == true) {
          setFork3positions([nforkpositions[2]]);
        } else {
          setFork3positions([]);
        }
        break;
      case 4:
        if (data.hasGoods == true) {
          setFork4positions([nforkpositions[3]]);
        } else {
          setFork4positions([]);
        }
        break;
      default:
        break;
    }
    //更新堆垛机信息
    srminfo[data.srmCode - 1] = data;
    setSrminfo(srminfo);
  }

  // 添加状态来控制弹窗信息
  const [modalInfo, setModalInfo] = useState<{
    position: THREE.Vector3;
    color?: THREE.Color;
    srmInfo?: SrmInfo;
    covInfo?: CovInfo; // 可以是单个对象或数组
    covInfos?: CovInfo[]; // 可以是单个对象或数组
    info?: GoodsInfo;
  } | null>(null);

  // 修改点击处理函数
  const handleModelClick = (
    position: THREE.Vector3,
    color: THREE.Color,
    info: GoodsInfo
  ) => {
    setModalInfo({ position, color, info });
  };

  // 修改点击处理函数
  const handleModelClick1 = (
    position: THREE.Vector3,
    infom: SrmInfo | CovInfo[] | CovInfo
  ) => {
    if (isSrmInfoArray(infom)) {
      // 处理 SrmInfo[]
      const srmInfo = infom;
      setModalInfo({ position, srmInfo });
    } else {
      if (Array.isArray(infom)) {
        // 处理 CovInfo 数组
        const covInfos: CovInfo[] = infom;
        setModalInfo({ position, covInfos });
      } else {
        const covInfo: CovInfo = infom;
        // 处理单个 CovInfo 对象
        setModalInfo({ position, covInfo });
      }
    }
  };

  function isSrmInfoArray(arr: any): arr is SrmInfo {
    return arr !== null && typeof arr === "object" && "srmCode" in arr; // 判断是否为对象且包含 srmCode 字段
  }

  // 弹窗只显示一次，根据 modalInfo 状态
  useEffect(() => {
    if (modalInfo) {
      Modal.info({
        title: "设备信息",
        content: (
          <div>
            <div>
              {/* info存在则展示信息 */}
              {modalInfo.info && (
                <div>
                  <strong>托盘编码:</strong> {modalInfo.info.palletCode} <br />
                  <strong>库位号:</strong> {modalInfo.info.binNo} <br />
                  <strong>库位名称:</strong> {modalInfo.info.binName} <br />
                  <strong>物料编码:</strong> {modalInfo.info.materialNo} <br />
                  <strong>物料名称:</strong> {modalInfo.info.materialName}{" "}
                  <br />
                  <strong>入库时间:</strong> {modalInfo.info.inTime} <br />
                  <strong>装载类型:</strong> {modalInfo.info.loadType} <br />
                </div>
              )}
              {modalInfo.srmInfo &&
                Object.keys(modalInfo.srmInfo).length > 0 && (
                  <div>
                    <ul>
                      <li>
                        <strong>堆垛机编码:</strong> {modalInfo.srmInfo.srmCode}{" "}
                        <br />
                        <strong>错误代码:</strong> {modalInfo.srmInfo.errCode}{" "}
                        <br />
                        <strong>运行模式:</strong> {modalInfo.srmInfo.runMode}{" "}
                        <br />
                        <strong>X坐标:</strong> {modalInfo.srmInfo.x} <br />
                        <strong>Y坐标:</strong> {modalInfo.srmInfo.y} <br />
                        <strong>Z坐标:</strong> {modalInfo.srmInfo.z} <br />
                        <strong>流水号:</strong> {modalInfo.srmInfo.serialNo}{" "}
                        <br />
                        <strong>功能码:</strong> {modalInfo.srmInfo.funcCode}{" "}
                        <br />
                        <strong>托盘编码:</strong>{" "}
                        {modalInfo.srmInfo.palletCode} <br />
                        <strong>排:</strong> {modalInfo.srmInfo.row} <br />
                        <strong>列:</strong> {modalInfo.srmInfo.col} <br />
                        <strong>层:</strong> {modalInfo.srmInfo.layer} <br />
                        <strong>库台号:</strong> {modalInfo.srmInfo.shelfNo}{" "}
                        <br />
                        <strong>是否有货物:</strong>{" "}
                        {modalInfo.srmInfo.hasGoods ? "是" : "否"} <br />
                      </li>
                    </ul>
                  </div>
                )}
              {modalInfo.covInfos &&
                Object.keys(modalInfo.covInfos).length > 0 && (
                  <div>
                    <div style={{ display: "flex", flexWrap: "wrap" }}>
                      {Object.entries(modalInfo.covInfos).map(
                        (
                          [_, info],
                          index // 使用 _ 来代替未使用的 deviceCode
                        ) => (
                          <div
                            key={index}
                            style={{ flex: "1 1 45%", margin: "10px" }}
                          >
                            <strong>设备编码:</strong> {info.deviceCode} <br />
                            <strong>错误代码:</strong> {info.errCode} <br />
                            <strong>出入模式:</strong> {info.runMode} <br />
                            <strong>上料口侧是否有货物:</strong>{" "}
                            {info.hasGoods ? "是" : "否"} <br />
                            <strong>上料口托盘编码:</strong> {info.onCode}{" "}
                            <br />
                            <strong>缓存侧是否有货物:</strong>{" "}
                            {info.hasGoodsCache ? "是" : "否"} <br />
                            <strong>缓存侧托盘编码:</strong> {info.midCode}{" "}
                            <br />
                            <strong>入库口侧是否有货物:</strong>{" "}
                            {info.hasGoodsIn ? "是" : "否"} <br />
                            <strong>入库口托盘编码:</strong> {info.downCode}{" "}
                            <br />
                            <strong>移载平台侧是否有货物:</strong>{" "}
                            {info.hasGoodsMove ? "是" : "否"} <br />
                            <strong>X坐标:</strong> {info.x} <br />
                            <strong>Z坐标:</strong> {info.z} <br />
                            <strong>设备状态:</strong> {info.status} <br />
                          </div>
                        )
                      )}
                    </div>
                  </div>
                )}
              {modalInfo.covInfo &&
                Object.keys(modalInfo.covInfo).length > 0 && (
                  <div>
                    <div style={{ display: "flex", flexWrap: "wrap" }}>
                      <div>
                        <strong>设备编码:</strong>{" "}
                        {modalInfo.covInfo.deviceCode} <br />
                        <strong>托盘编码:</strong> {modalInfo.covInfo.onCode}{" "}
                        <br />
                        <strong>错误代码:</strong>{" "}
                        {modalInfo.covInfo.errCode !== null
                          ? modalInfo.covInfo.errCode
                          : "无错误代码"}{" "}
                        <br />
                        <strong>运转方向:</strong>{" "}
                        {modalInfo.covInfo.runMode === "入"
                          ? "高->低"
                          : "低->高"}{" "}
                        <br />
                        <strong>低巷道是否有货:</strong>{" "}
                        {modalInfo.covInfo.hasGoods ? "是" : "否"} <br />
                        <strong>高巷道是否有货物:</strong>{" "}
                        {modalInfo.covInfo.hasGoodsCache ? "是" : "否"} <br />
                        <strong>移载平台侧是否有货物:</strong>{" "}
                        {modalInfo.covInfo.hasGoodsMove ? "是" : "否"} <br />
                        <strong>X坐标:</strong> {modalInfo.covInfo.x} <br />
                        <strong>Z坐标:</strong> {modalInfo.covInfo.z} <br />
                        <strong>设备状态:</strong> {modalInfo.covInfo.status}{" "}
                        <br />
                      </div>
                    </div>
                  </div>
                )}
            </div>
          </div>
        ),
        onOk() {
          setModalInfo(null); // 在关闭弹窗时重置 modalInfo
        },
      });
    }
  }, [modalInfo]); // 监听 modalInfo 状态变化

  return (
    <div>
      {/* 信息显示区域 */}
      {/* 报警信息全为无时，不渲染这块区域 */}
      {!Object.values(errorCodes).every((code) => code === "无") && (
        <div
          style={{
            position: "absolute",
            top: "10px",
            left: "10px",
            backgroundColor: "rgba(255, 0, 0, 0.8)",
            color: "white",
            padding: "10px",
            borderRadius: "5px",
            zIndex: 1000, // 确保这个区域在其他元素之上
          }}
        >
          <h4>报警信息</h4>
          <div>
            {errorCodes.srm1 !== "无" && (
              <div>
                <strong>1号堆垛机:</strong> {errorCodes.srm1} <br />
              </div>
            )}
            {errorCodes.srm2 !== "无" && (
              <div>
                <strong>2号堆垛机:</strong> {errorCodes.srm2} <br />
              </div>
            )}
            {errorCodes.srm3 !== "无" && (
              <div>
                <strong>3号堆垛机:</strong> {errorCodes.srm3} <br />
              </div>
            )}
            {errorCodes.srm4 !== "无" && (
              <div>
                <strong>4号堆垛机:</strong> {errorCodes.srm4} <br />
              </div>
            )}
            {errorCodes.cv1 !== "无" && (
              <div>
                <strong>输送线1:</strong> {errorCodes.cv1} <br />
              </div>
            )}
            {errorCodes.cv2 !== "无" && (
              <div>
                <strong>输送线2:</strong> {errorCodes.cv2} <br />
              </div>
            )}
            {errorCodes.cv3 !== "无" && (
              <div>
                <strong>输送线3:</strong> {errorCodes.cv3} <br />
              </div>
            )}
            {errorCodes.cv4 !== "无" && (
              <div>
                <strong>输送线4:</strong> {errorCodes.cv4} <br />
              </div>
            )}
            {errorCodes.cv5 !== "无" && (
              <div>
                <strong>输送线5:</strong> {errorCodes.cv5} <br />
              </div>
            )}
            {errorCodes.cv6 !== "无" && (
              <div>
                <strong>输送线6:</strong> {errorCodes.cv6} <br />
              </div>
            )}
            {errorCodes.cv7 !== "无" && (
              <div>
                <strong>输送线7:</strong> {errorCodes.cv7} <br />
              </div>
            )}
            {errorCodes.cv8 !== "无" && (
              <div>
                <strong>输送线8:</strong> {errorCodes.cv8} <br />
              </div>
            )}
            {errorCodes.cv9 !== "无" && (
              <div>
                <strong>输送线9:</strong> {errorCodes.cv9} <br />
              </div>
            )}
            {errorCodes.cv10 !== "无" && (
              <div>
                <strong>输送线10:</strong> {errorCodes.cv10} <br />
              </div>
            )}
            {errorCodes.cv11 !== "无" && (
              <div>
                <strong>输送线11:</strong> {errorCodes.cv11} <br />
              </div>
            )}
            {errorCodes.cv12 !== "无" && (
              <div>
                <strong>输送线12:</strong> {errorCodes.cv12} <br />
              </div>
            )}
            {errorCodes.port1 !== "无" && (
              <div>
                <strong>港口1:</strong> {errorCodes.port1} <br />
              </div>
            )}
            {errorCodes.port2 !== "无" && (
              <div>
                <strong>港口2:</strong> {errorCodes.port2} <br />
              </div>
            )}
            {errorCodes.port3 !== "无" && (
              <div>
                <strong>港口3:</strong> {errorCodes.port3} <br />
              </div>
            )}
            {errorCodes.port4 !== "无" && (
              <div>
                <strong>港口4:</strong> {errorCodes.port4} <br />
              </div>
            )}
            {errorCodes.port5 !== "无" && (
              <div>
                <strong>港口5:</strong> {errorCodes.port5} <br />
              </div>
            )}
            {errorCodes.port6 !== "无" && (
              <div>
                <strong>港口6:</strong> {errorCodes.port6} <br />
              </div>
            )}
          </div>
        </div>
      )}

      <Canvas
        style={{
          width: "100vw",
          height: "100vh",
          // backgroundColor: '#66c519',
        }}
      >
        <ambientLight intensity={1} />
        <directionalLight intensity={1.5} position={[5, 10, 7]} />
        <pointLight position={[10, 10, 10]} />
        {/* 添加坐标轴辅助线 */}
        {/* 50 表示坐标轴长度 */}
        {/* <axesHelper args={[50]} /> */}
        {/* 添加网格辅助线 100 表示网格大小, 100 表示分割数 */}
        {/* <gridHelper args={[100, 100]} /> */}
        <MainScene
          url="/models/MainScene.glb"
          position={new THREE.Vector3(0, 0, 7)}
          onClick={() => {}}
        />
        使用 map 渲染多个 Model 组件
        {positions.map(
          (position: THREE.Vector3, index: Key | null | undefined) => {
            const key = `${position.x},${position.y},${position.z}`;
            const color = colorMap[key] || new THREE.Color("#FFFFFF"); // 获取颜色映射
            const positionInfo = positionInfoMap[key] || {
              x: 0,
              y: 0,
              z: 0,
              palletCode: "",
              binName: "",
              binNo: "",
              materialName: "",
              materialNo: "",
              inTime: "",
              loadType: "",
            }; // 获取位置信息映射
            return (
              <SubScene
                key={index}
                url="/models/SubScene.glb"
                position={position}
                onClick={handleModelClick}
                color={color}
                info={positionInfo}
              />
            );
          }
        )}
        {/* 设备上的货物 */}
        {wpositions.map((position, index) => (
          <Forks key={index} url="/models/SubScene.glb" position={position} />
        ))}
        {portpositions.map((position, index) => (
          <Other
            key={index}
            url="/models/port.glb"
            position={position}
            onClick={handleModelClick1}
            infom={[covinfo[2 * index + 12], covinfo[2 * index + 13]]}
          />
        ))}
        {cvpositions.map((position, index) => (
          <Other
            key={index}
            url="/models/cv.glb"
            position={position}
            onClick={handleModelClick1}
            infom={covinfo[index]}
          />
        ))}
        {srmpositions.map((position, index) => (
          <Other
            key={index}
            url="/models/Srm.glb"
            position={position}
            onClick={handleModelClick1}
            infom={srminfo[index]}
          />
        ))}
        {fork1positions.map((position, index) => (
          <Forks key={index} url="/models/fork.glb" position={position} />
        ))}
        {fork2positions.map((position, index) => (
          <Forks key={index} url="/models/fork.glb" position={position} />
        ))}
        {fork3positions.map((position, index) => (
          <Forks key={index} url="/models/fork.glb" position={position} />
        ))}
        {fork4positions.map((position, index) => (
          <Forks key={index} url="/models/fork.glb" position={position} />
        ))}
        {nforkpositions.map((position, index) => (
          <Forks key={index} url="/models/nfork.glb" position={position} />
        ))}
        {/* <OrbitControls /> */}
        <OrbitControls
          maxPolarAngle={Math.PI / 2} // 限制向上旋转
          target={new THREE.Vector3(22, 0, 3.5175)} // 设置旋转中心为场景中心
        />
      </Canvas>
    </div>
  );
}
